using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace BepuPhysics.Collidables
{
    public enum ContinuousDetectionMode
    {
        /// <summary>
        /// <para>不执行专用的连续检测。默认推测性联系人生成将在推测性边际内进行。</para>
        /// <para>可碰撞边界框的扩展速度不会超出推测边距。</para>
        /// <para>这是最便宜的模式,但它可能会错过冲突。请注意,如果可碰撞离散模式正在快速移动,则其边界框未展开的事实
        /// 即使使用非离散的可碰撞对象,也可能导致其错过冲突。</para>
        /// </summary>
        Discrete = 0,
        /// <summary>
        /// <para>不执行专用的连续检测。默认推测性联系人生成将在推测性边际内进行。</para>
        /// <para>如有必要,可碰撞的边界框将以超出推测边距的速度扩展。</para>
        /// 当可碰撞对象可能快速移动并且本身不需要连续检测,但存在具有连续模式的其他可碰撞对象时,这很有用
        /// 这应该可以避免丢失冲突。</para>
        /// </summary>
        Passive = 1,
        /// <summary>
        /// <para>碰撞检测将从扫描测试开始,以确定可能的碰撞时间。将为预测的冲突生成推测性联系人。</para>
        /// <para>这种模式可以捕捉角运动,几乎不会发生鬼影碰撞。然而,它可能会错过由于主要碰撞的速度变化而可能发生的二次碰撞。</para>
        /// </summary>
        Continuous = 2,
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct ContinuousDetectionSettings
    {
        /// <summary>
        /// 连续碰撞检测模式。
        /// </summary>
        [FieldOffset(0)]
        public ContinuousDetectionMode Mode;
        /// <summary>
        /// 如果使用ContinuousDetectionMode.Continuity,则MinimumSweepTimestep是搜索第一次影响时扫描测试将取得的最小进度。
        /// 扫描测试可能会错过持续时间小于MinimumProgress的碰撞。使用较大的值可以显著提高扫描测试的性能。
        /// </summary>
        [FieldOffset(4)]
        public float MinimumSweepTimestep;
        /// <summary>
        /// 如果使用ContinuousDetectionMode.Continuity,如果影响区域的时间已细化为小于SweepConvergenceThreshold,则扫描测试将终止。
        /// 接近于零的值将更接近于撞击的真实时间,但对于投机性接触生成,较大的值通常可以很好地工作。
        /// 值越大,扫描结束的时间就越早,可以显著提高扫描性能。
        /// </summary>
        [FieldOffset(8)]
        public float SweepConvergenceThreshold;

        public bool AllowExpansionBeyondSpeculativeMargin { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return (uint)Mode > 0; } }

        /// <summary>
        /// <para>不会执行专门的连续检测。默认推测性联系人生成将在推测性边际内进行。</para>
        /// <para>可碰撞边界框的扩展速度不会超出推测边距。</para>
        /// <para>这是最便宜的模式,但它可能会错过冲突。请注意,如果可碰撞离散模式正在快速移动,则其边界框未展开的事实
        /// 即使使用非离散的可碰撞对象,也可能导致其错过冲突。</para>
        /// </summary>
        public static ContinuousDetectionSettings Discrete
        {
            get { return new ContinuousDetectionSettings(); }
        }

        /// <summary>
        /// <para>不执行专用的连续检测。默认推测性联系人生成将在推测性边际内进行。</para>
        /// <para>如有必要,可碰撞的边界框将以超出推测边距的速度扩展。</para>
        /// 当可碰撞对象可能快速移动并且本身不需要连续检测,但存在具有连续模式的其他可碰撞对象时,这很有用
        /// 这应该可以避免丢失冲突。</para>
        /// </summary>
        public static ContinuousDetectionSettings Passive
        {
            get { return new ContinuousDetectionSettings() { Mode = ContinuousDetectionMode.Passive }; }
        }

        /// <summary>
        /// <para>碰撞检测将从扫描测试开始,以确定可能的碰撞时间。将为预测的冲突生成推测性联系人。</para>
        /// <para>这种模式可以捕捉角运动,几乎不会发生鬼影碰撞。然而,它可能会错过由于主要碰撞的速度变化而可能发生的二次碰撞。</para>
        /// </summary>
        /// <param name="minumSweepTimestep">搜索第一次影响时扫描测试将取得的最小进度。
        /// 扫描测试可能会错过持续时间小于MinimumProgress的碰撞。使用较大的值可以显著提高扫描测试的性能。</param>
        /// <param name="SweepConvergenceThreshold">阈值,将影响区域的时间与扫描终止进行比较。
        /// 如果区域已细化为小于SweepConvergenceThreshold,则扫掠将终止。
        /// 接近于零的值将更接近于撞击的真实时间,但对于投机性接触生成,较大的值通常可以很好地工作。
        /// 值越大,扫描结束的时间就越早,可以显著提高扫描性能。</param>
        /// <return>反映连续检测模式的设置。</return>
        public static ContinuousDetectionSettings Continuous(float minimumSweepTimestep, float sweepConvergenceThreshold)
        {
            return new ContinuousDetectionSettings { Mode = ContinuousDetectionMode.Continuous, MinimumSweepTimestep = minimumSweepTimestep, SweepConvergenceThreshold = sweepConvergenceThreshold };
        }
    }

    /// <summary>
    /// 描述处于较宽阶段且能够生成冲突对的可冲突实例。
    /// ShapeIndex指向Nothing(默认构造的TypedIndex)的Collidables实际上不引用任何现有的Colliable。
    /// 这可用于不需要可碰撞表示的实体。
    /// </summary>
    public struct Collidable
    {
        /// <summary>
        /// 此可碰撞对象的连续碰撞检测设置。包括要使用的碰撞检测模式以及与这些模式关联的调整变量。
        /// </summary>
        public ContinuousDetectionSettings Continuity;

        /// <summary>
        /// 主体使用的形状的索引。虽然这是可以改变的,但从无形状->有形状或有形状->无形状的任何转变都必须报告给宽泛的阶段。
        /// 如果需要执行这样的转换,请考虑使用Bodies.ChangeShape或Bodies.ApplyDescription;这些函数会更新相关状态。
        /// </summary>
        public TypedIndex Shape;
        /// <summary>
        /// 可以在其中生成接触的形状表面周围的页边距大小。这些接触将具有负深度,并且仅在帧的速度
        /// 会把一对的形状推向重叠。这应该是正数,以避免抖动。它也可以用作连续冲突检测的一种形式,但过度
        /// 较高的值与快速运动相结合可能会导致可见的"重影碰撞"瑕疵。
        /// <para>对于不太可能发生重影冲突的连续冲突检测,请使用专用的连续冲突检测模式。</para>
        /// </summary>
        public float SpeculativeMargin;
        /// <summary>
        /// 宽相位中可碰撞的指数。用于查找边界框散布的目标位置。在正常情况下,这不应在外部设置。
        /// </summary>
        public int BroadPhaseIndex;

    }
}
